#include <string.h>
#include "os_api.h"
#include "sys_glb.h"
#include "app.h"
#include "app_afn.h"
#include "mw_nram.h"
#include "drv_uart.h"
#include "drv_sys.h"
#include "app_isdp.h"
#include "app_slc_drv_bl0942b.h"
#include "app_slc_datetime.h"
#ifdef IDLE_CHECK_SYS_PARA_MSG_FLG
#include "reg_check.h"
#endif

typedef BOOL (*APP_MSG_FUNC)( U8 *p_msg_data, U16 len );
typedef struct
{
	MSG_APP_T m_msg_id;
	APP_MSG_FUNC m_func_entry;
}APP_MSG_FUNC_OBJ_T;

static void app_main_tsk( void *param );

static MSG_HDR_T g_app_que_buff[APP_MSG_ITEM_LEN];
static isOS_QUE g_app_que;

static isOS_TCB g_app_tsk;
static isOS_STACK g_app_tsk_stack[TSK_STK_SIZE_APP];

const isOS_TskInfo c_app_tskinfo=
{
	app_main_tsk,				//-- task function
	NULL,						//-- task function parameter
	g_app_tsk_stack,			//-- task stack end addr in memory
	TSK_STK_SIZE_APP,			//-- task stack size (in isOS_S32,not bytes)
	"App task",					//-- task name
	TSK_PRIO_APP,				//-- task priority
};

BOOL g_app_msg_rel_flg = FALSE;
BOOL app_alive_check_proc(U8 *p_user_data, U16 len );
BOOL g_app_task_alive_flg = FALSE;

const APP_MSG_FUNC_OBJ_T c_app_msg_func_list[] = 
{
	MSG_HOSTIF_TO_APP_DATA, app_host_dispatch,
	MSG_HOSTIF_TO_APP_ERR, app_afn_rsp_status,
	MSG_PLC_TO_APP_DATA, app_afn_dlt_report,
	MSG_PLC_TO_APP_STAT, app_afn_rsp_status,

	MSG_IDLE_TO_APP_CHECK, app_alive_check_proc,
#ifdef EVENT_REPORT
	MSG_PLC_TO_APP_ENA_REG, app_afn_event_reg_ena,
	MSG_PLC_TO_APP_EVENT_ACK, app_afn_event_report_ack,
	MSG_PLC_TO_APP_BIND_OK, app_afn_event_bind_ok,
	MSG_PLC_TO_APP_BIND_DISMISS, app_afn_event_bind_dismiss,
#endif
	MSG_PLC_TO_APP_DEBUG, isdp_cmd_plc_debug_report,
#ifdef PING_MT_FLG
	MSG_PLC_TO_APP_PING_MT, app_afn_debug_ping_mt,
#endif
#ifdef MAC_READ_FLG
	MSG_APP_TO_APP_MAC_REQ_TMOUT, app_afn_mac_req_proc,
#endif

#ifdef EVENT_REPORT
#ifdef EVENT_QUERY_FLG
	MSG_APP_TO_APP_EVENT_QRY, app_afn_event_query,
#endif
	MSG_APP_TO_APP_EVENT_SND, app_afn_event_snd2plc,
#endif

	MSG_MEA_TO_APP, app_bl0942b_mea_manage,
#ifdef MEAMULTINITFLG
	MSG_MEA_INIT_TO_APP, app_bl0942b_init_manage,
#endif

	MSG_TIME_TO_APP_UPDATE,app_update_datetime_proc,
	MSG_TIME_TO_APP_LEAKAGE,app_leakage_message_proc,
	MSG_TIME_TO_FRESH_RELAYOUT,app_relayout_fresh_proc,

#ifdef IDLE_CHECK_SYS_PARA_MSG_FLG
	MSG_IDLE_TO_APP_PARA_CHECK,app_idle_tsk_check_sys_para_proc,
#endif
#ifdef SLC_RELAY_AUTO_CTRL_FLG
	MSG_RELAY_AUTO_CTRL,app_slc_relay_auto_ctrl_proc,
#endif
	MSG_APP_END, NULL,
};

/****************************************************************************** 
                     Implementation
*******************************************************************************/

/*
* Function Name:
*   app_msg_rel_flg_set
* Description:
*   App AFN message release flag set
* Parameters:
*   BOOL msg_rel_flg:
* Returns:
*   :
* Author				Date 
*  Jerry				2011-3-27   
* Note:
*    
*/
void app_msg_rel_flg_set( BOOL msg_rel_flg )
{
	g_app_msg_rel_flg = msg_rel_flg;
}

/*
* Function Name:
*   app_msg_rel_flg_get
* Description:
*   App AFN message release flag get
* Parameters:
*   None
* Returns:
*   :
* Author				Date 
*  Jerry				2011-3-27   
* Note:
*    
*/
BOOL app_msg_rel_flg_get( void )
{
	return g_app_msg_rel_flg;
}

/*
* Function Name:
*   app_main_tsk
* Description:
*   Application main task
* Parameters:
*   void *param
* Returns:
* Author				Date 
*  Jerry				2009-10-26   
* Note:
*    
*/
static void app_main_tsk( void *param )
{
	isOS_S32 result;
	MSG_HDR_T msg_hdr;
	U8 *p_msg_data;

	/* Module initialiaze */
    ext_flash_init();
	bu_mw_Nram_init();
#ifdef BAUD_SAVE
	app_afn_baud_load();
#endif

	app_afn_module_init();
	for(;;)
	{
		result = isOS_QueueReceive( &g_app_que, &msg_hdr,  \
							   TM_WAIT_FOREVER );
		if (pdPASS == result )
		{	// return Success
			const APP_MSG_FUNC_OBJ_T *p_app_msg_obj;
			APP_MSG_FUNC p_func_entry;
			drv_sys_wdt_feed();

			if ( msg_hdr.m_len )
			{	// Data region is validate, data from pointer of m_pointer
				p_msg_data = (U8*)msg_hdr.m_pointer;
			}
			else
			{	// No have data region, dword parameter will convey through m_pointer(U32)
				p_msg_data = (U8*)&msg_hdr.m_pointer;
			}

			//$$$$$$$$$$$$$$$$$$$$$$$ Release Host if's busy indicator

			app_msg_rel_flg_set( FALSE );

			// Dispatch
			p_app_msg_obj = c_app_msg_func_list;
			while(p_app_msg_obj->m_func_entry)
			{
				if (p_app_msg_obj->m_msg_id == msg_hdr.m_msg_id )
				{
					break;
				}
				p_app_msg_obj++;
			}
			p_func_entry = p_app_msg_obj->m_func_entry;

			if (p_func_entry)
			{	// Call procedure
				p_func_entry( p_msg_data, msg_hdr.m_len );
			}

			if ( (!app_msg_rel_flg_get())&&msg_hdr.m_len )
			{	// Need release memory
				if (!sys_free( (U8*)p_msg_data ))
				{
					IS_ASSERT(0);
				}
			}
		}
	} 
}

/*
* Function Name:
*   app_main_init
* Description:
*   Aplication Module initial
* Parameters:
* Returns:
* Author				Date 
*  Jerry				2009-10-26   
* Note:
*    
*/
void app_main_init( void )
{
	isOS_S32 ret;
	
	ret = isOS_QueueCreate( &g_app_que, (isOS_U8*)g_app_que_buff, \
							 APP_MSG_ITEM_LEN, sizeof(MSG_HDR_T) );
	if ( ret != pdPASS )
	{
		IS_ASSERT(0);
	}

	ret = isOS_TaskCreate( &g_app_tsk, \
						   &c_app_tskinfo,
						   OS_TASK_START_ON_CREATION
						   );
	if ( ret != pdPASS )
	{
		IS_ASSERT(0);
	}

}

/*
* Function Name:
*   app_msg_snd
* Description:
*   Application Message send
* Parameters:
*   U16 msg_id: Message ID
*  	U8* p_msg_data: Message data or Attached data
*  	U16 msg_len: length of message data
* Returns:
*   BOOL:
* Author				Date 
*  Jerry				2009-10-27   
* Note:
*    
*/
void app_msg_send_fail_printf(void)
{
	U8 i;
	
	drv_uart_init(UART_BAUD_2400);
	for(i=0;i<10;i++)
	{
		drv_uart_send(&i,1,TRUE);
	}

	for(i=0;i<APP_MSG_ITEM_LEN;i++)
	{
		drv_uart_send((U8*)&(g_app_que_buff[i].m_msg_id),2,TRUE);
	}
	drv_uart_send((U8*)&(g_app_que.header_cnt),2,TRUE);
	drv_uart_send((U8*)&(g_app_que.tail_cnt),2,TRUE);
}
BOOL app_msg_snd( U16 msg_id, U8 *p_msg_data, U16 msg_len )
{
	MSG_HDR_T msg_hdr;
	msg_hdr.m_msg_id = msg_id;
	if ( msg_len )
	{
		msg_hdr.m_len = msg_len;
		msg_hdr.m_pointer = (U32)p_msg_data;
	}
	else
	{
		msg_hdr.m_len = 0;
		msg_hdr.m_pointer = (U32)*p_msg_data++;
		msg_hdr.m_pointer += ((U32)*p_msg_data++<<8);
		msg_hdr.m_pointer += ((U32)*p_msg_data++<<16);
		msg_hdr.m_pointer += ((U32)*p_msg_data++<<24);
	}
	if ( pdPASS !=isOS_QueueSend( &g_app_que, &msg_hdr, TM_POLLING ) )
	{
		IS_ASSERT(0);
		//app_msg_send_fail_printf();
		return FALSE;
	}
	return TRUE;
}

void app_msg_snd_alive_check(void)
{
	app_msg_snd(MSG_IDLE_TO_APP_CHECK,NULL,0);		// to app_main_tsk
}
BOOL app_alive_check_proc(U8 *p_user_data, U16 len )
{
	g_app_task_alive_flg = TRUE;
	return TRUE;
}
/*
* Function Name:
*   app_main_que_empty
* Description:
*   app main queue empty
* Parameters:
* Returns:
*   BOOL: TRUE( empty ), FALSE( not empty )
* Author				Date 
*  Jerry				2011-5-31   
* Note:
*    
*/
BOOL app_main_que_empty( void )
{
	return isOS_QueueIsEmpty(&g_app_que);
}
